<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 100%;
            height: 100vh;
            background-color: #d1c9c9;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: row;
        }

        .center {
            width: 70%;
            height: 100%;
            background-color: #dbdbdb;
            /* display: flex;
            justify-content: center;
            align-items: center; */
            display: block;
            overflow: scroll;
            /* text-align: center; */
            text-align: right;
        }

        .option {
            width: 30%;
            height: 100%;
            overflow: scroll;
            background-color: #f8f2e5;
            display: block;
            /* justify-content: center;
            align-items: center;
            flex-direction: column; */
        }

        .option-item {
            display: flex;
            justify-content: flex-start;
            align-items: center;
            margin: 5px;
            width: 90%;
            font-size: 15px;
        }

        input {
            height: 37px;
            border-radius: 7px;
            border-width: 1px;
            outline: none;
            padding: 0 7px;
            box-sizing: border-box;
            margin: 3px 5px;
        }

        #canvasP canvas {
            border: 1px solid #fefefe !important;
            margin: 50px;
        }

        .input1 {
            width: 20%;
        }

        .value {
            display: block;
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
        }

        .value-item {
            display: inline-block;
            margin: 10px;
            padding: 15px;
            border: 1px solid #b6b1b1;

        }

        button {
            height: 30px;
            margin: 5px;
            border-radius: 7px;
            outline: none;
            border-width: 0;
            background-color: #8b77fc;
            color: #fff;
        }

        ::-webkit-scrollbar {
            display: none
        }
    </style>
</head>

<body>
    <div class="box">
        <div class="center" id="canvasP">
            <canvas id="myCanvas" width="300" height="300"></canvas>
            <div id="myCanvasList"></div>
        </div>
        <div class="option">
            <div action="javascript:" class="form1"
                style="display: flex; flex-direction: column; justify-content: center;">
                <div class="option-item">
                    <div style="margin: 5px;">画布宽度</div>
                    <input type="number" name="CanvasWeight" value="300">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">光源位置</div>
                    <input type="number" style="display: none;" name="SourceX" value="50" placeholder="光源位置的x轴">
                    <input type="number" name="SourceY" value="300" min="300" placeholder="光源位置的y轴">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;white-space: nowrap">遮罩圆心</div>
                    <div style="display: flex; flex-direction: column;">
                        <input type="number" name="MaskX" value="60" placeholder="遮罩圆心的x轴">
                        <input type="number" name="MaskY" value="" placeholder="和底部相切，可以不填y轴">
                        <input type="number" name="MaskR" value="24" placeholder="半径">
                    </div>
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">开口角度（角度数）</div>
                    <input type="number" name="Opening1" value="46" placeholder="遮罩开口开始">
                    <input type="number" name="Opening2" value="108" placeholder="遮罩开口结束">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">曲线控制点下</div>
                    <input type="number" name="curveC_x" value="65" placeholder="曲线控制点x">
                    <input type="number" name="curveC_y" value="300" placeholder="曲线控制点y">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">曲线控制点上</div>
                    <input type="number" style="height: 40px;" name="direction_C_x" value="28" placeholder="曲线控制点x">
                    <input type="number" style="height: 40px;" name="direction_C_y" value="-10" placeholder="曲线控制点y">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">曲线开始位置</div>
                    <input type="number" name="curveC_start_x" value="35" placeholder="曲线宽度">
                    <input type="number" name="curveC_start_y" value="110" placeholder="曲线宽度">
                </div>
                <div class="option-item">
                    <div style="margin: 5px;">曲线结束位置</div>
                    <input type="number" name="curveC_end_x" value="140" placeholder="曲线宽度">
                    <input type="number" name="curveC_end_y" value="120" placeholder="曲线宽度">
                </div>
                <div class="option-item">
                    <button onclick="submit()">绘制图形</button>
                    <button onclick="reset()">重置</button>
                    <!-- <button type="" onclick="complex()" style="color: red;">初步展示部分条件</button> -->
                    <button type="" onclick="downLoad()" style="color: #ffab2e;">下载图片png</button>
                </div>
            </div>
            <div class="" style="padding: 10px;">
                其他设置
                <div style="display: flex;">
                    <div class="option-item" style="align-items: center;flex-grow: 3; width: auto;">
                        <input type="checkbox" name="intercept" value="ok" style="width: 20px; height: 20px;" />是否截取
                    </div>
                    <div class="option-item" style="align-items: center;flex-grow: 3; width: auto;">
                        <input type="checkbox" name="transparent" value="ok" style="width: 20px; height: 20px;" />背景透明
                    </div>
                    <div class="option-item" style="align-items: center;flex-grow: 3; width: auto;">
                        <input type="checkbox" name="absolute" value="ok" style="width: 20px; height: 20px;" />固定区透明
                    </div>
                </div>


                <div style="display: flex;">
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-colpick@3.1.0/css/colpick.css">
                    <div class="option-item" style="align-items: center;">
                        <div class="color-box" style="width: 50px; height: 50px; background: #ccc; margin: 0 5px;">
                        </div> 图形颜色
                    </div>
                    <div class="option-item" style="align-items: center;">
                        <div class="color-box-bg" style="width: 50px; height: 50px; background: #ccc; margin: 0 5px;">
                        </div> 背景颜色
                    </div>
                    <div class="option-item" style="align-items: center;">
                        <div class="color-box-bg-absolute"
                            style="width: 50px; height: 50px; background: #ccc; margin: 0 5px;">
                        </div> 固定区颜色
                    </div>
                </div>

            </div>
            <div class="value">
                <!-- <div class="value-item " onclick="setFormValue()">134</div> -->
            </div>
        </div>
    </div>

    <script src="./jquery.3.5.1.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery-colpick@3.1.0/js/colpick.min.js"></script>
    <script src="./utils.js"></script>

    <script>
        class Local {
            constructor() {
                this.initLo();
            }
            setData(key, value) { // 保存键值对到本地
                if (typeof value === 'string') {
                    return localStorage.setItem(key, value);
                }
                try {
                    localStorage.setItem(key, JSON.stringify(value));
                } catch (err) {
                    return err;
                }
            }
            getData(key) { // 获取指定key的数据
                const value = localStorage.getItem(key);
                try {
                    return JSON.parse(value);
                } catch (err) {
                    return value;
                }
            }
            removeData(key) { // 删除指定key的数据
                return localStorage.removeItem(key);
            }
            clearData() { // 删除所有的本地数据
                return localStorage.clear();
            }
            initLo() { // 初始化
                if (!window.localStorage) {
                    throw new Error("浏览器不支持 localstorage 本地存储！！！")
                }
            }
        }
        var local = new Local()

        function setData(data) {
            return local.setData('test2', data)
        }

        function getData(data) {
            return local.getData('test2')
        }
    </script>
    <script>

        // setInterval(setPoint, 100)

        var formData = {},
            myCanvas = '',
            color = '',
            colorBg = '',
            colorBgAbsolute = '',
            currentFocus = ''

        // 选中颜色
        $('.color-box').colpick({
            layout: 'rgbhex',
            // 颜色的格式
            //submit: true,           // 是否显示确认按钮
            //flat: true,             // 是否初始化的时候就显示
            // submitText: '确定',       // 确认按钮文本
            // color: '#f33548',         // 默认颜色
            // colorScheme: 'dark',    // 主题
            onSubmit: function (hsb, hex, rgb, el) {
                $(el).css('background-color', '#' + hex);
                $(el).colpickHide();
                color = '#' + hex
                localStorage.setItem("color", color)
                verification(formData)
            }
        });
        $('.color-box-bg').colpick({
            layout: 'rgbhex',
            onSubmit: function (hsb, hex, rgb, el) {
                $(el).css('background-color', '#' + hex);
                $(el).colpickHide();
                colorBg = '#' + hex
                localStorage.setItem("colorBg", colorBg)
                verification(formData)
            }
        });
        $('.color-box-bg-absolute').colpick({
            layout: 'rgbhex',
            onSubmit: function (hsb, hex, rgb, el) {
                $(el).css('background-color', '#' + hex);
                $(el).colpickHide();
                colorBgAbsolute = '#' + hex
                localStorage.setItem("colorBgAbsolute", colorBgAbsolute)
                verification(formData)
            }
        });

        // 选中焦点
        $('.form1 input').focus(function () {
            currentFocus = $(this).attr('name')
            verification(formData)
        })
        $('.form1 input').blur(function () {
            currentFocus = ''
            verification(formData)
        })

        // 获取到表单的值
        function getFormData() {
            // var form = $('.form1').serializeArray()

            var inputList = [];
            $('.form1 input').each(function (index, item) {
                // console.log('', item)
                inputList.push({
                    name: $(item).attr('name'),
                    value: $(item).val()
                })
                formData[$(item).attr('name')] = Number($(item).val());
            })
            return inputList;
        }

        function submit() {
            var form = getFormData()
            setData(form)
            verification(formData)
            return false;
        }

        // 清空-复原
        function reset() {
            var init = {
                "CanvasWeight": 300,
                "SourceY": 300,
                "MaskX": 60,
                // "MaskY": '',
                "MaskR": 24,
                "Opening1": 46,
                "Opening2": 108,
                "curveC_x": 65,
                "curveC_y": 300,
                "direction_C_x": 28,
                "direction_C_y": -10,
                "curveC_start_x": 35,
                "curveC_start_y": 110,
                "curveC_end_x": 140,
                "curveC_end_y": 120,
            }
            Object.keys(init).forEach(function (item) {
                $(`[name="${item}"]`).val(Number(init[item]))
            })
            var form = getFormData()
            setData(form)
            verification(formData)
            $('.form1 [name="CanvasWeight"]').change()
        }

        ;
        (function init() {
            var form = getData() || []
            for (let index = 0; index < form.length; index++) {
                const element = form[index];
                if (!element.name) continue;
                formData[element.name] = Number(element.value);
                $(`[name="${element.name}"]`).val(element.value)
                if (element.name == 'CanvasWeight')
                    $('#myCanvas').attr({
                        width: element.value,
                        height: element.value,
                    })
            }

            if (localStorage.getItem("intercept") == 'true') {
                $(`[name="intercept"]`).prop('checked', true)
            }

            if (localStorage.getItem("transparent") == 'true') {
                $(`[name="transparent"]`).prop('checked', true)
            }

            if (localStorage.getItem("absolute") == 'true') {
                $(`[name="absolute"]`).prop('checked', true)
            }

            color = localStorage.getItem("color") || '#ef1c26'
            colorBg = localStorage.getItem("colorBg") || '#ffffff'
            colorBgAbsolute = localStorage.getItem("colorBgAbsolute") || '#000000'
            $('.color-box').css("background", color)
            $('.color-box-bg').css("background", colorBg)
            $('.color-box-bg-absolute').css("background", colorBgAbsolute)

            verification(formData)
        })()

        // 监听表单
        $(`[name="intercept"]`).change(function () {
            var form = getFormData()
            setData(form)
            var checked = $(this).prop('checked')
            localStorage.setItem("intercept", checked);
            location.reload()
        })
        $(`[name="transparent"]`).change(function () {
            var form = getFormData()
            setData(form)
            var checked = $(this).prop('checked')
            localStorage.setItem("transparent", checked);
            verification(formData)
            // location.reload()
        })
        $(`[name="absolute"]`).change(function () {
            var form = getFormData()
            setData(form)
            var checked = $(this).prop('checked')
            localStorage.setItem("absolute", checked);
            verification(formData)
        })
        $('.form1 [name="CanvasWeight"]').change(function (res) {
            var $this = $(this);
            console.log('', $this.val())
            $('#myCanvas').attr({
                width: $this.val(),
                height: $this.val(),
            })
            // if ($('[name="SourceY"]').val() < $this.val()) $('[name="SourceY"]').val($this.val() - $(
            //     '[name="MaskR"]').val())
            $('[name="SourceY"]').val($this.val() * formData.SourceY / formData.CanvasWeight)
            $('[name="MaskX"]').val($this.val() * formData.MaskX / formData.CanvasWeight)
            // $('[name="MaskY"]').val($this.val() * formData.MaskY / formData.CanvasWeight)
            $('[name="MaskR"]').val($this.val() * formData.MaskR / formData.CanvasWeight)
            $('[name="curveC_width"]').val($this.val() * formData.curveC_width / formData
                .CanvasWeight)
            $('[name="curveC_x"]').val($this.val() * formData.curveC_x / formData.CanvasWeight)
            $('[name="curveC_y"]').val($this.val() * formData.curveC_y / formData.CanvasWeight)

            $('[name="direction_start_x"]').val($this.val() * formData.direction_start_x / formData
                .CanvasWeight)
            $('[name="direction_start_y"]').val($this.val() * formData.direction_start_y / formData
                .CanvasWeight)
            $('[name="direction_C_x"]').val($this.val() * formData.direction_C_x / formData
                .CanvasWeight)
            $('[name="direction_C_y"]').val($this.val() * formData.direction_C_y / formData
                .CanvasWeight)
            $('[name="curveC_start_x"]').val($this.val() * formData.curveC_start_x / formData
                .CanvasWeight)
            $('[name="curveC_start_y"]').val($this.val() * formData.curveC_start_y / formData
                .CanvasWeight)
            $('[name="curveC_end_x"]').val($this.val() * formData.curveC_end_x / formData
                .CanvasWeight)
            $('[name="curveC_end_y"]').val($this.val() * formData.curveC_end_y / formData
                .CanvasWeight)

            $('[name="SourceY"]').attr({
                min: Math.floor($this.val() - $('[name="MaskR"]').val()),
            })

            // verification(formData)
        })
        $('.form1 input').change(function () {
            var form = getFormData()
            verification(formData)
        })

        function downLoad() {
            var url = myCanvas.toDataURL("image/png");
            var oA = document.createElement("a");
            oA.download = '图片'; // 设置下载的文件名，默认是'下载'
            oA.href = url;
            document.body.appendChild(oA);
            oA.click();
            oA.remove(); // 下载之后把创建的元素删除
        }

        function complex(formData_ = formData) {
            var form = $('.form1').serializeArray()
            for (let index = 0; index < form.length; index++) {
                const element = form[index];
                if (!element.name) continue;
                formData[element.name] = element.value;
            }

            SourceY = complexData(formData.SourceY, 30, 3) // 光源位置

            MaskX = complexData(formData_.MaskX, 30, 3) // 遮罩圆心x轴
            // MaskR = complexData(formData_.MaskR, 30, 3) // 遮罩圆心半径

            // Opening1 = complexData(formData_.Opening1, 30, 3) // 遮罩开口开始
            // Opening2 = complexData(formData_.Opening2, 30, 3) // 遮罩开口结束

            // curveC_width = complexData(30, 30, 5) // 为了计算曲线的开始点位置不在 光源和起始开口 的连线上

            // curveC_x = complexData(30, 30, 3)   // 为了计算曲线的开始点位置不在 光源和起始开口 的连线上

            // var arrList = combinationFn2([SourceX, SourceY, MaskX, MaskR, Opening1, Opening2, curveC_width])
            var arrList = combinationFn([SourceY, MaskX])

            index = 0
            var time = setInterval(() => {
                var ele = arrList[index]
                formData_.SourceY = ele[0];
                formData_.MaskX = ele[1];

                formData_.index = index
                formData_.choice = true

                // console.log('', formData_)

                verification(formData_) // 展示所有图形
                index++;
                if (index > arrList.length - 1)
                    clearInterval(time), formData_.choice = false
            }, 20);

            console.log('', arrList.length)
        }

        // 限制光源在开口的垂线中间
        function Source(formData) {
            var focusStart = focusTip(formData.MaskX, formData.MaskY, formData.MaskR, formData.Opening1) // 遮罩开口开始点的坐标
            var focusEnd = focusTip(formData.MaskX, formData.MaskY, formData.MaskR, +formData.Opening1 + +formData
                .Opening2) // 遮罩开口结束点的坐标
            var mid = [(focusStart[0] + focusEnd[0]) / 2, (focusStart[1] + focusEnd[1]) / 2]
            x = mid[0] - (formData.SourceY - mid[1]) * (focusStart[1] - focusEnd[1]) / (focusStart[0] - focusEnd[0])
            formData.SourceX = x
        }

        // 限定规则
        function verification(formData) {
            // 条件：圆底部和底线(图中橙色先)相切，也就是它的圆心离下边框的距离不能大于半径r
            formData.MaskY = formData.CanvasWeight - formData.MaskR
            // 规则：限制光源在开口的垂线中间
            Source(formData)
            // 规则1：光源高度 > 画布宽度-圆半径，否则默认等于画布高度
            // if (formData.SourceY < formData.CanvasWeight - formData.MaskR) formData.SourceY = formData.CanvasWeight;
            // 规则1：光源高度 > 画布宽度-圆半径，否则退出
            if (formData.SourceY < formData.CanvasWeight - formData.MaskR) return;


            var goldenLine = formData.CanvasWeight / 2; // 中间长度
            var goldenLine_2 = formData.CanvasWeight * 0.618; // 黄金分割

            var goldenLine_2_2 = formData.goldenLine_2_2 = goldenLine_2 / 2; // 黄金分割的一半
            var focusStart = formData.focusStart = focusTip(formData.MaskX, formData.MaskY, formData.MaskR, formData
                .Opening1) // 遮罩开口开始点的坐标
            var focusEnd = formData.focusEnd = focusTip(formData.MaskX, formData.MaskY, formData.MaskR, +formData
                .Opening1 + +formData
                    .Opening2) // 遮罩开口结束点的坐标
            var focusX_Start = formData.focusX_Start = focusX(formData.SourceX, formData.SourceY, focusStart[0],
                focusStart[
                1]) // 光源通过起始开口和x轴相切的点
            var focusX_End = formData.focusX_End = focusX(formData.SourceX, formData.SourceY, focusEnd[0], focusEnd[
                1]) // 光源通过结束开口和x轴相切的点

            if (formData.curveC_end_x > goldenLine) formData.curveC_end_x = goldenLine; // 曲线的结束位置不能大于中轴
            if (formData.direction_C_x > goldenLine) formData.direction_C_x = goldenLine; // 左边曲线的控制点位置不能大于中轴 ，为后面的处理方便
            if (formData.curveC_start_x > formData.curveC_end_x) formData.curveC_start_x = formData
                .curveC_end_x; // 曲线的结束位置不能大于中轴


            formData.Source = Point(formData.SourceX, formData.SourceY)
            formData.focusX_StartP = Point(focusX_Start[0], focusX_Start[1])
            formData.focusX_EndP = Point(focusX_End[0], focusX_End[1])

            formData.Source2 = Point(formData.CanvasWeight - formData.SourceX, formData.SourceY)
            formData.focusX_StartP2 = Point(formData.CanvasWeight - focusX_Start[0], focusX_Start[1])
            formData.focusX_EndP2 = Point(formData.CanvasWeight - focusX_End[0], focusX_End[1])

            setCanvas(formData)
        }

        // setCanvas(formData)
        function setCanvas(formData) {
            if (Object.keys(formData).length == 0) return;

            // var canvas = document.getElementById(`canvas-${count}`);
            var canvas;
            if (formData.choice) {
                $("#myCanvasList").append(
                    `<canvas id="myCanvasList-${index}" width="${formData.CanvasWeight}" height="${formData.CanvasWeight}"></canvas>`
                )
                canvas = document.getElementById(`myCanvasList-${formData.index}`);
            } else canvas = myCanvas = document.getElementById(`myCanvas`);
            if (canvas.getContext) {
                var context = canvas.getContext('2d');
                clearCanvas(context)

                // 截取 start
                if ($(`[name="intercept"]`).prop('checked')) {
                    // context.save();
                    context.beginPath();
                    context.arc(formData.CanvasWeight / 2, formData.CanvasWeight / 2, formData.CanvasWeight / 2, 0, 2 * Math.PI);
                    context.fillStyle = '#fefefe00'
                    // context.fill();
                    // context.stroke()
                    context.clip();
                    // context.clip("nonzero");
                    context.closePath();
                }
                // 截取 end

                // 背景颜色
                if (!$(`[name="transparent"]`).prop('checked')) {
                    context.beginPath();
                    context.rect(0, 0, formData.CanvasWeight, formData.CanvasWeight)
                    context.fillStyle = colorBg || '#ffffff';
                    context.fill();
                    // context.stroke()
                    context.closePath();
                }

                context.beginPath();
                context.moveTo(formData.focusStart[0], formData.focusStart[1]); // 画遮罩开口开始

                var SourcePositive = setB(context, formData.Source, formData.focusX_StartP, formData.focusX_EndP)

                /* 
                    @Source 光源坐标
                    @focusX_StartP 光源通过起始开口和x轴相切的点 
                    @focusX_EndP 光源通过结束开口和x轴相切的点 
                */
                function setB(context, Source, focusX_StartP, focusX_EndP) {
                    var p0 = Point(formData.curveC_start_x, formData.curveC_start_y,) // 曲线开始点
                    var p0_0 = Point(formData.CanvasWeight - formData.curveC_start_x, formData
                        .curveC_start_y) // 曲线开始点-相反方向
                    var p1 = Point(formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -左边
                    var p2 = Point(formData.curveC_end_x, formData.curveC_end_y,) // 曲线结束点
                    var p2_2 = Point(formData.CanvasWeight - formData.curveC_end_x, formData
                        .curveC_end_y) // 曲线结束点-相反方向
                    var p3 = Point(formData.direction_C_x, formData.direction_C_y,) // 曲线上边控制点 -左边

                    // 
                    var leftPoint = []

                    // 左边上下边的曲线
                    var middleP = {
                        x: (p0.x + p2.x) / 2,
                        y: (p0.y + p2.y) / 2
                    }
                    // var middleP_X = focusX(formData.SourceX, formData.SourceY, middleP.x, middleP.y) // 
                    var middleP_X = focusX(Source.x, Source.y, middleP.x, middleP.y) // 
                    var besselList = CubicBezier2(p0, p3, p2) // 获取贝塞尔曲线的坐标
                    var header = [],
                        fool = [];
                    for (let index = 0; index < besselList.length; index++) {
                        const element = besselList[index];
                        // if (element.x < middleP.x) header.push(element)
                        // else fool.push(element)

                        var tt = focusX(Source.x, Source.y, element.x, element.y)
                        if (tt[0] < middleP_X[0]) header.push(element)
                        else fool.push(element)

                    }
                    header.reverse()
                    var besselList = CubicBezier2(p0, p1, p2) // 获取贝塞尔曲线的坐标
                    besselList = [...header, ...besselList]
                    // besselList = [...header, ...besselList, ...fool]
                    var isL = false; //  贝塞尔曲线和开口相交
                    var isR = false; // 贝塞尔曲线和结束相交

                    var tep = [];
                    for (let index = 0; index < besselList.length; index++) {
                        // var start = focusX(formData.SourceX, formData.SourceY, p0.x, p0.y)
                        // var end = focusX(formData.SourceX, formData.SourceY, p2.x, p2.y)
                        var start = focusX(Source.x, Source.y, p0.x, p0.y)
                        var end = focusX(Source.x, Source.y, p2.x, p2.y)
                        if (start[0] > focusX_EndP.x || end[0] < focusX_StartP.x) break;
                        const element = besselList[index];
                        var x = focusX(Source.x, Source.y, element.x, element.y);
                        if (tep.length == 0) {
                            tep.push(element);
                            continue;
                        }
                        var itemIndex = focusX(Source.x, Source.y, tep[tep.length - 1].x, tep[tep.length - 1]
                            .y); // 之前的点
                        if (x[0] <= itemIndex[0] && x[0] < middleP_X[0]) { // 左边
                            tep.pop()
                        }
                        if (x[0] >= itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            tep.push(element)
                            continue
                        }
                        if (x[0] < itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            break;
                        }
                        tep.push(element)
                    }
                    leftPoint.push(...tep)

                    var sb = BesselStraightFocus(Source, focusX_StartP, p0, p1, p2) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var eb = BesselStraightFocus(Source, focusX_EndP, p0, p1, p2) // 计算贝塞尔曲线和直线的交点（结束和曲线）
                    var st = BesselStraightFocus(Source, focusX_StartP, p0, p3, p2) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var et = BesselStraightFocus(Source, focusX_EndP, p0, p3, p2) // 计算贝塞尔曲线和直线的交点（结束和曲线）

                    if (sb.length != 0 || st.length != 0) {
                        var tep = [...sb, ...st];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = [tt]
                        leftPoint.forEach(function (item) {
                            if (item.x > tt.x) arr.push(item)
                        })
                        leftPoint = arr;
                        isL = true;
                    }

                    if (eb.length != 0 || et.length != 0) {
                        var tep = [...eb, ...et];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = []
                        leftPoint.forEach(function (item) {
                            if (item.x < tt.x) arr.push(item)
                        })
                        arr.push(tt)
                        leftPoint = arr
                        isR = true;
                    }

                    // 右边上下边的曲线
                    var leftPoint2 = [];
                    var p4 = Point(formData.CanvasWeight - formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -右边边
                    var p5 = Point(formData.CanvasWeight - formData.direction_C_x, formData
                        .direction_C_y) // 曲线上边控制点 -右边边
                    var middleP = {
                        x: (p0_0.x + p2_2.x) / 2,
                        y: (p0_0.y + p2_2.y) / 2
                    }
                    // var middleP_X = focusX(formData.SourceX, formData.SourceY, middleP.x, middleP.y) // 
                    var middleP_X = focusX(Source.x, Source.y, middleP.x, middleP.y) // 
                    var besselList = CubicBezier2(p2_2, p5, p0_0) // 获取贝塞尔曲线的坐标
                    var header = [],
                        fool = [];
                    for (let index = 0; index < besselList.length; index++) {
                        const element = besselList[index];
                        // if (element.x < middleP.x) header.push(element)
                        // else fool.push(element)

                        var tt = focusX(Source.x, Source.y, element.x, element.y)
                        if (tt[0] < middleP_X[0]) header.push(element)
                        else fool.push(element)
                    }
                    header.reverse()
                    header.pop()
                    var besselList = CubicBezier2(p2_2, p4, p0_0) // 获取贝塞尔曲线的坐标
                    besselList = [...header, ...besselList]
                    // besselList = [...header, ...besselList, ...fool]
                    var isL2 = false; //  贝塞尔曲线和开口相交
                    var isR2 = false; // 贝塞尔曲线和结束相交

                    var tep = [];
                    for (let index = 0; index < besselList.length; index++) {
                        var start = focusX(Source.x, Source.y, p2_2.x, p2_2.y)
                        var end = focusX(Source.x, Source.y, p0_0.x, p0_0.y)
                        // if (start[0] > focusX_EndP.x || end[0] < focusX_StartP.x) break;
                        const element = besselList[index];
                        var x = focusX(Source.x, Source.y, element.x, element.y);
                        if (tep.length == 0) {
                            tep.push(element);
                            continue;
                        }
                        var itemIndex = focusX(Source.x, Source.y, tep[tep.length - 1].x, tep[tep.length - 1]
                            .y); // 之前的点
                        if (x[0] <= itemIndex[0] && x[0] < middleP_X[0]) { // 左边
                            tep.pop()
                        }
                        if (x[0] <= focusX_StartP.x) { // 左边
                            tep.pop()
                            continue
                        }
                        if (x[0] > itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            tep.push(element)
                            continue
                        }
                        if (x[0] < itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            break
                        }
                        tep.push(element)
                    }
                    leftPoint2.push(...tep)
                    // debugger;

                    var sb = BesselStraightFocus(Source, focusX_StartP, p2_2, p4, p0_0) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var eb = BesselStraightFocus(Source, focusX_EndP, p2_2, p4, p0_0) // 计算贝塞尔曲线和直线的交点（结束和曲线）
                    var st = BesselStraightFocus(Source, focusX_StartP, p2_2, p5, p0_0) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var et = BesselStraightFocus(Source, focusX_EndP, p2_2, p5, p0_0) // 计算贝塞尔曲线和直线的交点（结束和曲线）


                    var aa = focusX(Source.x, Source.y, leftPoint2[0].x, leftPoint2[0].y)
                    var bb = focusX(Source.x, Source.y, leftPoint2[leftPoint2.length - 1].x, leftPoint2[leftPoint2
                        .length - 1].y)
                    if (aa[0] > focusX_EndP.x || bb[0] < focusX_StartP.x) {
                        leftPoint2 = []
                    }

                    if (sb.length != 0 || st.length != 0) {
                        var tep = [...sb, ...st];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = [tt]
                        // leftPoint2.forEach(function (item) {
                        //     if (item.x > tt.x) arr.push(item)
                        // })
                        leftPoint2.forEach(function (item) {
                            if (item.y > tt.y) arr.push(item)
                        })
                        leftPoint2 = arr
                        isL2 = true;
                    }

                    if (eb.length != 0 || et.length != 0) {
                        var tep = [...eb, ...et];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = []
                        // leftPoint2.forEach(function (item) {
                        //     if (item.x < tt.x) arr.push(item)
                        // })
                        leftPoint2.forEach(function (item) {
                            if (item.y < tt.y) arr.push(item)
                        })
                        arr.push(tt)
                        leftPoint2 = arr
                        isR2 = true;
                    }

                    // 画图
                    if (!isL) context.lineTo(focusX_StartP.x, focusX_StartP.y); // 和曲线没有交点，则画光源与曲线起点连线的x轴的连线
                    if (leftPoint.length == 0) {
                        var tep = focusX(formData.SourceX, formData.SourceY, focusX_StartP.x, focusX_StartP.y)
                        context.lineTo(tep[0], tep[1]);
                    }
                    leftPoint.forEach(function (item, index) {
                        if (index == 0 && !isL) {
                            var tep = focusX(formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                        context.lineTo(item.x, item.y);
                        if (index == leftPoint.length - 1 && formData.curveC_end_x != formData.CanvasWeight /
                            2) {
                            var tep = focusX(formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                    })
                    leftPoint2.forEach(function (item, index) {
                        if (index == 0 && !isL2 && formData.curveC_end_x != formData
                            .CanvasWeight / 2) {
                            var tep = focusX(formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                        context.lineTo(item.x, item.y);
                        if (index == leftPoint2.length - 1) {
                            var tep = focusX(formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                    })

                    return [leftPoint, leftPoint2, isL, isR, isL2, isR2]
                }

                context.lineTo(formData.focusX_End[0], formData.focusX_End[1]); // 光源通过结束开口和x轴相切的点

                context.lineTo(formData.focusEnd[0], formData.focusEnd[1]); // 画遮罩开口结束
                context.closePath();
                // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                context.fillStyle = color || '#cc4057';
                context.fill();

                // =====================================
                // =====================================
                // =====================================
                // =====================================

                context.beginPath();
                context.moveTo(formData.CanvasWeight - formData.focusEnd[0], formData.focusEnd[1]); // 画遮罩开口开始

                // setB(context, formData.Source2, formData.focusX_StartP2, formData.focusX_EndP2)
                var SourceReverse = setC(context, formData.Source2, formData.focusX_EndP2, formData.focusX_StartP2)

                /* 
                    @Source 光源坐标
                    @focusX_StartP 光源通过起始开口和x轴相切的点 
                    @focusX_EndP 光源通过结束开口和x轴相切的点 
                */
                function setC(context, Source, focusX_StartP, focusX_EndP) {
                    var p0 = Point(formData.curveC_start_x, formData.curveC_start_y,) // 曲线开始点
                    var p0_0 = Point(formData.CanvasWeight - formData.curveC_start_x, formData
                        .curveC_start_y) // 曲线开始点-相反方向
                    var p1 = Point(formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -左边
                    var p2 = Point(formData.curveC_end_x, formData.curveC_end_y,) // 曲线结束点
                    var p2_2 = Point(formData.CanvasWeight - formData.curveC_end_x, formData
                        .curveC_end_y) // 曲线结束点-相反方向
                    var p3 = Point(formData.direction_C_x, formData.direction_C_y,) // 曲线上边控制点 -左边

                    // // 
                    var leftPoint = []
                    // 左边上下边的曲线
                    var middleP = {
                        x: (p0.x + p2.x) / 2,
                        y: (p0.y + p2.y) / 2
                    }
                    // var middleP_X = focusX(formData.SourceX, formData.SourceY, middleP.x, middleP.y) // 
                    var middleP_X = focusX(Source.x, Source.y, middleP.x, middleP.y) // 
                    var besselList = CubicBezier2(p0, p3, p2) // 获取贝塞尔曲线的坐标
                    var header = [],
                        fool = [];
                    for (let index = 0; index < besselList.length; index++) {
                        const element = besselList[index];
                        // if (element.x < middleP.x) header.push(element)
                        // else fool.push(element)

                        var tt = focusX(Source.x, Source.y, element.x, element.y)
                        if (tt[0] < middleP_X[0]) header.push(element)
                        else fool.push(element)
                    }
                    header.reverse()
                    fool.reverse()
                    var besselList = CubicBezier2(p0, p1, p2) // 获取贝塞尔曲线的坐标
                    // besselList = [...header, ...besselList]
                    besselList = [...besselList, ...fool]
                    var isL = false; //  贝塞尔曲线和开口相交
                    var isR = false; // 贝塞尔曲线和结束相交
                    // debugger;

                    var tep = [];
                    for (let index = 0; index < besselList.length; index++) {
                        var start = focusX(Source.x, Source.y, p0.x, p0.y)
                        var end = focusX(Source.x, Source.y, p2.x, p2.y)
                        // if (start[0] > focusX_EndP.x || end[0] < focusX_StartP.x) break;
                        const element = besselList[index];
                        var x = focusX(Source.x, Source.y, element.x, element.y);
                        if (tep.length == 0) {
                            tep.push(element);
                            continue;
                        }
                        var itemIndex = focusX(Source.x, Source.y, tep[tep.length - 1].x, tep[tep.length - 1]
                            .y); // 之前的点
                        if (x[0] <= itemIndex[0] && x[0] < middleP_X[0]) { // 左边
                            tep.pop()
                        }
                        if (x[0] < focusX_StartP.x) { // 左边
                            tep.pop()
                            continue
                        }
                        if (x[0] > itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            tep.push(element)
                            continue
                        }
                        if (x[0] < itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            break
                        }
                        tep.push(element)
                    }
                    leftPoint.push(...tep)
                    // debugger;

                    var sb = BesselStraightFocus(Source, focusX_StartP, p0, p1, p2) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var eb = BesselStraightFocus(Source, focusX_EndP, p0, p1, p2) // 计算贝塞尔曲线和直线的交点（结束和曲线）
                    var st = BesselStraightFocus(Source, focusX_StartP, p0, p3, p2) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var et = BesselStraightFocus(Source, focusX_EndP, p0, p3, p2) // 计算贝塞尔曲线和直线的交点（结束和曲线）


                    if (leftPoint.length != 0) {
                        var aa = focusX(Source.x, Source.y, leftPoint[0].x, leftPoint[0].y)
                        var bb = focusX(Source.x, Source.y, leftPoint[leftPoint.length - 1].x, leftPoint[leftPoint
                            .length - 1].y)
                        if (aa[0] > focusX_EndP.x || bb[0] < focusX_StartP.x) {
                            leftPoint = []
                        }
                    }

                    if (sb.length != 0 || st.length != 0) {
                        var tep = [...sb, ...st];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var aa = focusX(Source.x, Source.y, tt.x, tt.y)
                        var arr = [tt]
                        leftPoint.forEach(function (item) {
                            var bb = focusX(Source.x, Source.y, item.x, item.y)
                            if (bb[0] > aa[0]) arr.push(item)
                        })
                        leftPoint = arr
                        isL = true;
                    }

                    if (eb.length != 0 || et.length != 0) {
                        var tep = [...eb, ...et];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var aa = focusX(Source.x, Source.y, tt.x, tt.y)
                        var arr = []
                        leftPoint.forEach(function (item) {
                            var bb = focusX(Source.x, Source.y, item.x, item.y)
                            if (bb[0] < aa[0]) arr.push(item)
                            // if (item.x < tt.x) arr.push(item)
                        })
                        arr.push(tt)
                        leftPoint = arr;
                        isR = true;
                    }


                    // 右边上下边的曲线
                    var leftPoint2 = [];
                    var p4 = Point(formData.CanvasWeight - formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -右边边
                    var p5 = Point(formData.CanvasWeight - formData.direction_C_x, formData
                        .direction_C_y) // 曲线上边控制点 -右边边
                    var middleP = {
                        x: (p0_0.x + p2_2.x) / 2,
                        y: (p0_0.y + p2_2.y) / 2
                    }
                    // var middleP_X = focusX(formData.SourceX, formData.SourceY, middleP.x, middleP.y) // 
                    var middleP_X = focusX(Source.x, Source.y, middleP.x, middleP.y) // 
                    var besselList = CubicBezier2(p2_2, p5, p0_0) // 获取贝塞尔曲线的坐标
                    var header = [],
                        fool = [];
                    for (let index = 0; index < besselList.length; index++) {
                        const element = besselList[index];
                        // if (element.x < middleP.x) header.push(element)
                        // else fool.push(element)

                        var tt = focusX(Source.x, Source.y, element.x, element.y)
                        if (tt[0] < middleP_X[0]) header.push(element)
                        else fool.push(element)
                    }
                    header.reverse()
                    fool.reverse()
                    var besselList = CubicBezier2(p2_2, p4, p0_0) // 获取贝塞尔曲线的坐标
                    besselList = [...besselList, ...fool]
                    // besselList = [...header, ...besselList, ...fool]
                    var isL2 = false; //  贝塞尔曲线和开口相交
                    var isR2 = false; // 贝塞尔曲线和结束相交
                    // debugger;

                    var tep = [];
                    for (let index = 0; index < besselList.length; index++) {
                        var start = focusX(Source.x, Source.y, p2_2.x, p2_2.y)
                        var end = focusX(Source.x, Source.y, p0_0.x, p0_0.y)
                        // if (start[0] > focusX_EndP.x || end[0] < focusX_StartP.x) break;
                        const element = besselList[index];
                        var x = focusX(Source.x, Source.y, element.x, element.y);
                        if (tep.length == 0) {
                            tep.push(element);
                            continue;
                        }
                        var itemIndex = focusX(Source.x, Source.y, tep[tep.length - 1].x, tep[tep.length - 1]
                            .y); // 之前的点
                        if (x[0] < itemIndex[0] && x[0] < middleP_X[0]) { // 左边
                            tep.pop()
                        }
                        if (x[0] < focusX_StartP.x) { // 左边
                            tep.pop()
                            continue
                        }
                        if (x[0] > itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            tep.push(element)
                            continue
                        }
                        if (x[0] < itemIndex[0] && x[0] > middleP_X[0]) { // 右边
                            break
                        }
                        tep.push(element)
                    }
                    leftPoint2.push(...tep)

                    var sb = BesselStraightFocus(Source, focusX_StartP, p2_2, p4, p0_0) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var eb = BesselStraightFocus(Source, focusX_EndP, p2_2, p4, p0_0) // 计算贝塞尔曲线和直线的交点（结束和曲线）
                    var st = BesselStraightFocus(Source, focusX_StartP, p2_2, p5, p0_0) // 计算贝塞尔曲线和直线的交点（开口和曲线）
                    var et = BesselStraightFocus(Source, focusX_EndP, p2_2, p5, p0_0) // 计算贝塞尔曲线和直线的交点（结束和曲线）

                    if (leftPoint2.length != 0) {
                        var aa = focusX(Source.x, Source.y, leftPoint2[0].x, leftPoint2[0].y)
                        var bb = focusX(Source.x, Source.y, leftPoint2[leftPoint2.length - 1].x, leftPoint2[leftPoint2
                            .length - 1].y)
                        if (aa[0] > focusX_EndP.x || bb[0] < focusX_StartP.x) {
                            leftPoint2 = []
                        }
                    }

                    if (sb.length != 0 || st.length != 0) {
                        var tep = [...sb, ...st];
                        console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = [tt]
                        leftPoint2.forEach(function (item) {
                            if (item.x > tt.x) arr.push(item)
                        })
                        leftPoint2 = arr;
                        isL2 = true;
                    }

                    if (eb.length != 0 || et.length != 0) {
                        var tep = [...eb, ...et];
                        // console.log('tep', tep)
                        var tt = tep.length != 0 ? tep[0] : {};
                        tep.forEach(function (item) {
                            if (item.y > tt.y) tt = item;
                        })
                        // console.log('tt', tt)
                        var arr = []
                        leftPoint2.forEach(function (item) {
                            if (item.x < tt.x) arr.push(item)
                        })
                        arr.push(tt)
                        leftPoint2 = arr;
                        isR2 = true;
                    }

                    // 画图
                    if (!isL) context.lineTo(focusX_StartP.x, focusX_StartP.y); // 和曲线没有交点，则画光源与曲线起点连线的x轴的连线
                    if (leftPoint.length == 0) {
                        var tep = focusX(formData.SourceX, formData.SourceY, focusX_StartP.x, focusX_StartP.y)
                        context.lineTo(tep[0], tep[1]);
                    }
                    leftPoint.forEach(function (item, index) {
                        if (index == 0 && !isL) {
                            var tep = focusX(formData.CanvasWeight - formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                        context.lineTo(item.x, item.y);
                        if (index == leftPoint.length - 1 && formData.curveC_end_x != formData.CanvasWeight /
                            2) {
                            var tep = focusX(formData.CanvasWeight - formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                    })
                    leftPoint2.forEach(function (item, index) {
                        if (index == 0 && !isL2 && formData.curveC_end_x != formData
                            .CanvasWeight / 2) {
                            var tep = focusX(formData.CanvasWeight - formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                        context.lineTo(item.x, item.y);
                        if (index == leftPoint2.length - 1) {
                            var tep = focusX(formData.CanvasWeight - formData.SourceX, formData.SourceY, item.x, item.y)
                            context.lineTo(tep[0], tep[1]);
                        }
                    })

                    return [leftPoint, leftPoint2, isL, isR, isL2, isR2]
                }

                context.lineTo(formData.CanvasWeight - formData.focusX_Start[0], formData.focusX_Start[
                    1]); // 光源通过结束开口和x轴相切的点

                context.lineTo(formData.CanvasWeight - formData.focusStart[0], formData.focusStart[1]); // 画遮罩开口结束
                context.closePath();
                // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                context.fillStyle = color || '#cc4057';
                context.fill();

                // 遮挡部分圆的路径
                arc(formData.MaskX, formData.MaskY, formData.MaskR, context, color || '#cc4057')


                // 遮挡部分圆的路径
                arc(formData.CanvasWeight - formData.MaskX, formData.MaskY, formData.MaskR, context, color || '#cc4057')

                // // 开口的起始点
                // arc(formData.focusStart[0], formData.focusStart[1], 5, context, '#ffffff')

                // // 开口的结束点
                // arc(formData.focusEnd[0], formData.focusEnd[1], 5, context, '#ffffff')

                // // 光源
                // arc(formData.SourceX, formData.SourceY, 5, context)


                // // 开口的起始点
                // arc(formData.CanvasWeight - formData.focusStart[0], formData.focusStart[1], 5, context, '#ffffff')

                // // 开口的结束点
                // arc(formData.CanvasWeight - formData.focusEnd[0], formData.focusEnd[1], 5, context, '#ffffff')

                // // 光源
                // arc(formData.CanvasWeight - formData.SourceX, formData.SourceY, 5, context)


                // console.log('', SourcePositive)
                // console.log('', SourceReverse)

                // 画上边的遮罩区
                if (SourcePositive[0].length !== 0 && !SourcePositive[2] && !SourcePositive[3]) {
                    var p0 = Point(formData.curveC_start_x, formData.curveC_start_y,) // 曲线开始点
                    var p0_0 = Point(formData.CanvasWeight - formData.curveC_start_x, formData.curveC_start_y) // 曲线开始点-相反方向
                    var p1 = Point(formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -左边
                    var p2 = Point(formData.curveC_end_x, formData.curveC_end_y,) // 曲线结束点
                    var p2_2 = Point(formData.CanvasWeight - formData.curveC_end_x, formData.curveC_end_y) // 曲线结束点-相反方向
                    var p3 = Point(formData.direction_C_x, formData.direction_C_y,) // 曲线上边控制点 -左边
                    var p4 = Point(formData.CanvasWeight - formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -右边边
                    var p5 = Point(formData.CanvasWeight - formData.direction_C_x, formData.direction_C_y)  // 曲线上边控制点 -右边边

                    context.beginPath();
                    // context.moveTo(SourcePositive[0][0].x - 1, SourcePositive[0][0].y); // 画遮罩开口开始
                    context.moveTo(p0.x, p0.y); // 画遮罩开口开始
                    context.quadraticCurveTo(p3.x, p3.y, p2.x-1, p2.y);
                    var ff = segmentsIntr(  // 两个直线相交
                        { x: formData.CanvasWeight - formData.SourceX, y: formData.SourceY },
                        { x: SourceReverse[1][0].x, y: SourceReverse[1][0].y },
                        { x: formData.SourceX, y: formData.SourceY },
                        { x: SourcePositive[0][SourcePositive[0].length - 1].x, y: SourcePositive[0][SourcePositive[0].length - 1].y })
                    var Lx = focusX(formData.CanvasWeight - formData.SourceX, formData.SourceY,
                        SourceReverse[1][0].x, SourceReverse[1][0].y) //  光源和左边最后个切口的x轴

                    context.lineTo(ff.x, ff.y); // 
                    context.lineTo(Lx[0], 0); // 
                    context.lineTo(formData.focusX_StartP.x, 0);
                    context.lineTo(SourcePositive[0][0].x, SourcePositive[0][0].y); //   

                    context.closePath();
                    context.fillStyle = color || '#cc4057';
                    // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                    context.fill();

                    // 相反
                    context.beginPath();
                    // context.moveTo(SourceReverse[1][0].x - 1, SourceReverse[1][0].y); // 画遮罩开口开始
                    context.moveTo(p2_2.x, p2_2.y); // 画遮罩开口开始
                    context.quadraticCurveTo(p5.x, p5.y, p0_0.x, p0_0.y);
                    context.lineTo(SourceReverse[1][SourceReverse[1].length - 1].x, SourceReverse[1][SourceReverse[1].length - 1].y); //   
                    var Lx = focusX(formData.SourceX, formData.SourceY, SourcePositive[0][SourcePositive[0].length - 1].x, SourcePositive[0][SourcePositive[0].length - 1].y) //  光源和左边最后个切口的x轴
                    var ff = segmentsIntr(  // 两个直线相交
                        { x: formData.CanvasWeight - formData.SourceX, y: formData.SourceY },
                        { x: SourceReverse[1][0].x, y: SourceReverse[1][0].y },
                        { x: formData.SourceX, y: formData.SourceY },
                        { x: SourcePositive[0][SourcePositive[0].length - 1].x, y: SourcePositive[0][SourcePositive[0].length - 1].y })
                    context.lineTo(formData.focusX_StartP2.x, 0); //  光源和结束开口
                    context.lineTo(Lx[0], 0); //   
                    context.lineTo(ff.x, ff.y); //   
                    context.closePath();
                    context.fillStyle = color || '#cc4057';
                    // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                    context.fill();

                    // 遮挡物中间的颜色 start  
                    if (!$(`[name="absolute"]`).prop('checked')) {
                        context.beginPath();
                        context.moveTo(p0.x, p0.y); // 画遮罩开口开始
                        context.quadraticCurveTo(p1.x, p1.y, p2.x, p2.y);
                        context.quadraticCurveTo(p3.x, p3.y, p0.x, p0.y);
                        context.fillStyle = colorBgAbsolute || '#cc4057';
                        // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                        context.fill();
                        context.closePath();

                        context.beginPath();
                        context.moveTo(p2_2.x, p2_2.y); // 画遮罩开口开始
                        context.quadraticCurveTo(p4.x, p4.y, p0_0.x, p0_0.y);
                        context.quadraticCurveTo(p5.x, p5.y, p2_2.x, p2_2.y);
                        context.fillStyle = colorBgAbsolute || '#cc4057';
                        // context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
                        context.fill();
                        context.closePath();
                    }

                    // 遮挡物中间的颜色 end

                }

                var p0 = Point(formData.curveC_start_x, formData.curveC_start_y,) // 曲线开始点
                var p0_0 = Point(formData.CanvasWeight - formData.curveC_start_x, formData
                    .curveC_start_y) // 曲线开始点-相反方向
                var p1 = Point(formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -左边
                var p2 = Point(formData.curveC_end_x, formData.curveC_end_y,) // 曲线结束点
                var p2_2 = Point(formData.CanvasWeight - formData.curveC_end_x, formData.curveC_end_y,) // 曲线结束点-相反方向
                var p3 = Point(formData.direction_C_x, formData.direction_C_y,) // 曲线上边控制点 -左边

                var p4 = Point(formData.CanvasWeight - formData.curveC_x, formData.curveC_y,) // 曲线下边控制点 -右边边
                var p5 = Point(formData.CanvasWeight - formData.direction_C_x, formData
                    .direction_C_y) // 曲线上边控制点 -右边边

                // var b = besselList = CubicBezier2(p0, p1, p2) // 获取贝塞尔曲线的坐标
                // b.forEach(function (item) {
                //     arc(item.x, item.y, 5, context,)
                // })
                // var b = besselList = CubicBezier2(p0, p3, p2) // 获取贝塞尔曲线的坐标
                // b.forEach(function (item) {
                //     arc(item.x, item.y, 5, context,)
                // })
                // var b = besselList = CubicBezier2(p0_0, p4, p2_2) // 获取贝塞尔曲线的坐标
                // b.forEach(function (item) {
                //     arc(item.x, item.y, 5, context,)
                // })
                // var b = besselList = CubicBezier2(p0_0, p5, p2_2) // 获取贝塞尔曲线的坐标
                // b.forEach(function (item) {
                //     arc(item.x, item.y, 5, context,)
                // })

                // 设置辅助点
                switch (currentFocus) {
                    case "SourceY":
                        arc(formData.SourceX, formData.SourceY, 5, context, '#000000')
                        break;
                    case 'MaskX':
                        arc(formData.MaskX, formData.MaskY, 5, context, '#000000')
                        break;
                    case 'MaskR':
                        context.beginPath();
                        context.moveTo(formData.MaskX, formData.MaskY);
                        context.lineTo(formData.MaskX - formData.MaskR, formData.MaskY);
                        context.stroke()
                        context.closePath()
                        // formData.focusStart
                        break;
                    case 'Opening1':
                        context.beginPath();
                        context.moveTo(formData.MaskX - formData.MaskR, formData.MaskY);
                        context.lineTo(formData.MaskX, formData.MaskY);
                        context.lineTo(formData.focusStart[0], formData.focusStart[1]);
                        context.stroke()
                        context.closePath()
                        arc(formData.MaskX, formData.MaskY, 2, context, '#000000')
                        break;
                    case 'Opening2':
                        context.beginPath();
                        context.moveTo(formData.MaskX - formData.MaskR, formData.MaskY);
                        context.lineTo(formData.MaskX, formData.MaskY);
                        context.lineTo(formData.focusEnd[0], formData.focusEnd[1]);
                        context.stroke()
                        context.closePath()
                        arc(formData.MaskX, formData.MaskY, 2, context, '#000000')
                        break;
                    case 'curveC_start_x':
                        arc(formData.curveC_start_x, formData.curveC_start_y, 5, context, '#000000')
                        break;
                    case 'curveC_start_y':
                        arc(formData.curveC_start_x, formData.curveC_start_y, 5, context, '#000000')
                        break;
                    case 'curveC_end_x':
                        arc(formData.curveC_end_x, formData.curveC_end_y, 5, context, '#000000')
                        break;
                    case 'curveC_end_y':
                        arc(formData.curveC_end_x, formData.curveC_end_y, 5, context, '#000000')
                        break;
                    case 'curveC_x':
                        context.beginPath();
                        context.moveTo(formData.curveC_start_x, formData.curveC_start_y);
                        context.lineTo(formData.curveC_x, formData.curveC_y);
                        context.lineTo(formData.curveC_end_x, formData.curveC_end_y);
                        context.stroke()
                        context.closePath()
                        arc(formData.curveC_x, formData.curveC_y, 2, context, '#000000')
                        break;
                    case 'curveC_y':
                        context.beginPath();
                        context.moveTo(formData.curveC_start_x, formData.curveC_start_y);
                        context.lineTo(formData.curveC_x, formData.curveC_y);
                        context.lineTo(formData.curveC_end_x, formData.curveC_end_y);
                        context.stroke()
                        context.closePath()
                        arc(formData.curveC_x, formData.curveC_y, 2, context, '#000000')
                        break;
                    case 'direction_C_x':
                        context.beginPath();
                        context.moveTo(formData.curveC_start_x, formData.curveC_start_y);
                        context.lineTo(formData.direction_C_x, formData.direction_C_y);
                        context.lineTo(formData.curveC_end_x, formData.curveC_end_y);
                        context.stroke()
                        context.closePath()
                        arc(formData.direction_C_x, formData.direction_C_y, 2, context, '#000000')
                        break;
                    case 'direction_C_y':
                        context.beginPath();
                        context.moveTo(formData.curveC_start_x, formData.curveC_start_y);
                        context.lineTo(formData.direction_C_x, formData.direction_C_y);
                        context.lineTo(formData.curveC_end_x, formData.curveC_end_y);
                        context.stroke()
                        context.closePath()
                        arc(formData.direction_C_x, formData.direction_C_y, 2, context, '#000000')
                        break;
                }
            }
        }
    </script>
</body>

</html>